home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Interactive Reference Guide
/
C-C++ Interactive Reference Guide.iso
/
c_ref
/
csource3
/
186_01
/
makeio.c
< prev
next >
Wrap
Text File
|
1985-08-21
|
12KB
|
380 lines
/* MAKEIO.C -- Input/Output and messaging for MAKE.C
*
* For information on compilation, see MAKE.C. For usage, see
* MAKE.DOC
*
* CREDITS:
*
* -- getline(), getblock(), stov(), err(), and serr() functions by
* Allen Holub (DDJ #106).
* -- prompt(), batch(), addfile(), push(), and pop() functions
* by James Pritchett.
* -- All code by Allen Holub adapted for BDS C (where necessary)
* by James Pritchett.
*
* Version 1.0 -- 10/28/85
* Version 1.1 -- 12/06/85
*/
#include <bdscio.h>
#include "make.h"
void prompt() /* This is an escape hatch */
{
printf("\nHit any key to execute commands (^C aborts)");
getchar();
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void batch() /* Make the batch file, getting command lines from
* the command stack.
*/
{
int i; /* Counter for $$$.SUB records */
char *com; /* Pointer to command line */
char subrec[128]; /* SUB file record */
int fd; /* For disk I/O calls */
/* In order to batch SUBMITs, first check to see if A:$$$.SUB currently
* exists. If so, seek to the end of file, and append new commands.
* If A:$$$.SUB does not exist, create it.
*/
if ((fd = open("A:$$$.SUB",1)) != ERROR)
seek(fd,0,2);
else if ((fd = creat("A:$$$.SUB")) == ERROR)
err("Can't create A:$$$.SUB\n",0);
/* NOTE: In a pending SUBMIT file, the commands must be in reverse
* order. Hence, commands are stored in a stack, with the commands
* pushed in the proper order, and thus popped in reverse order.
* Also, pending SUBMIT files must have their commands in a
* particular format: Each command must be preceded by a count of
* the number of chars in it; the commands must be null-terminated;
* and each command must be padded out to take up exactly one
* record (128 bytes) of the file.
*/
while (com = pop()) {
i = 0;
subrec[i++] = strlen(com)+1; /* put the length first */
while (i < 127 && *com) /* put the command line */
subrec[i++] = *(com++);
while (i < 128) /* pad with nulls */
subrec[i++] = 0;
if (write(fd,subrec,1) != 1) /* write this record */
err("Error in writing to A:$$$.SUB\n",0);
}
if(close(fd) == ERROR)
err("Error in closing A:$$$.SUB\n",0);
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
TNODE *addfile(file) /* Handle a file-dependancy. This function
* makes a node for the filename, evaluates
* truth/falsity by means of an attribute
* bit, and sets that bit after evaluation.
*/
char *file; /* Filename */
{
TNODE *nodep; /* Pointer to node made for this filename */
char fcb[36]; /* FCB for BDOS calls */
char *name; /* Filename as exists in directory */
int entry; /* Directory code returned from SEARCH_F call */
int i;
char curuser; /* Current user area */
char fileuser; /* User area of file */
/* Make the node for this file and place in tree. */
nodep = gmem(NODESIZE);
nodep->rnode = nodep->lnode = 0;
nodep->being_made = file;
nodep->depends_on = 0;
nodep->do_this = 0;
#ifdef DEBUG
debug("DEBUG addfile: Node made for %s\n",nodep->being_made);
#endif
tree(nodep,&root); /* place the node */
/* Handle any user area specified in filename */
curuser = bdos(GS_USER,0x0FF); /* Get current user */
/* If filename has a user spec (defined by '/'), set the new user
* and increment file past the '/'.
*/
if ((*(file+1) == '/') || (*(file+2) == '/')) {
if ((fileuser = atoi(file)) > MAXUSER)
fileuser = curuser;
while (*(file++) != '/')
;
}
/* If there is no user spec on filename, but there is a default user,
* set it accordingly.
*/
else if (defuser != UNKNOWN)
fileuser = defuser;
/* If no user spec and no default user, just stay put. */
else
fileuser = curuser;
/* Now, set that user! */
bdos(GS_USER,fileuser);
/* Find the file and check the attribute bit */
bdos(SET_DMA,DMA);
setfcb(fcb,file); /* Make an FCB for the filename */
if (!(*fcb)) /* If no drive name, use default */
*fcb = defdsk;
entry = bdos(SEARCH_F,fcb);
if (entry == 255) /* BDOS error code */
serr("Dependancy file %s does not exist\n",file);
else {
name = DMA + (entry*32); /* convert BDOS code to pointer */
/* If attribute is set, status = FALSE */
if (*(name+MATTRIB) & 0x80) {
nodep->changed = FALSE;
#ifdef DEBUG
debug("DEBUG addfile: File %s not changed\n",fcb+1);
#endif
}
/* Else, set status to TRUE and set bit again (-n and -r options
* override the attribute set).
*/
else {
#ifdef DEBUG
debug("DEBUG addfile: File %s changed\n",fcb+1);
#endif
nodep->changed = TRUE;
if (!nopt && !ropt) {
/* In order to preserve any other attributes that may be set for this
* file, the filename is copied from the directory (where attribute
* bits are set) to the FCB before setting MATTRIB.
*/
for (i = 1; i <= 11; i++)
fcb[i] = *(name+i);
fcb[MATTRIB] |= 0x80;
#ifdef PUBLIC
/* If using Plu*Perfect's public files system, the following must be
* done to keep public files in their proper place.
*/
if (*name != fileuser)
bdos(GS_USER,*name);
#endif
bdos(SET_ATT,fcb);
}
}
/* Now, reset the user to curuser before ending */
bdos(GS_USER,curuser);
return nodep;
}
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char *getline(maxline) /* Get one logical line from the file.
* Strips CR-LF's and returns null-terminated
* string. If EOF is encountered, returns 0.
* Else, returns pointer to the line.
*/
int maxline; /* Maximum line length */
{
char *bp; /* Pointer to line buffer (external) */
int c,lastc;
/* Read in a line, concatenating lines ending in '\' and terminating with
* CR-LF or CPMEOF. Line is placed in a temporary buffer of MAXLINE chars
* (linbuf[]) and then copied into free memory in order to save space.
*/
bp = linbuf;
while(1) {
inputline++;
for (lastc = 0; (c = getc(iobuff)) != CPMEOF
&& c != '\r'; lastc = c) {
if (--maxline > 0)
*bp++ = toupper(c); /* All input folded to uppercase */
}
if (c == '\r')
c = getc(iobuff); /* skip the CR in CR-LF pair */
if (!(c == '\n' && lastc == '\\'))
break; /* end of the line */
else if (maxline > 0) /* concatenate lines */
--bp;
else
err("Line too long (%d chars maximum)",MAXLINE);
}
*bp = 0; /* Terminate with null */
/* Allocate just enough space for the line and move it there. EOF or
* Out of memory returns 0
*/
if ((c == CPMEOF && bp == linbuf) || !(bp = alloc((bp-linbuf)+1))) {
return NULL;
}
strcpy(bp,linbuf);
return bp;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char **getblock() /* Get a block of lines ended by an empty line.
* Creates an array of pointers to those lines.
* This function is used to create the do_this
* arrays.
*/
{
char *p; /* Pointer to line of text from makefile */
char *lines[MAXBLOCK]; /* Local line vector */
char **blockv; /* Pointer to this vector */
int blockc; /* Count of lines in vector */
blockv = lines;
blockc = 0;
/* Read lines from file until a blank line is encountered. Skip over
* all white space, and place pointer to first char of text into the
* local line vector. Abort if too many lines.
*/
while (p = getline(MAXLINE)) {
if (!(*p))
break;
skipwhite(p);
if (++blockc <= MAXBLOCK)
*blockv++ = p;
else
err("Action too long (max = %d lines)",MAXBLOCK);
}
/* Allocate enough space for the line vector and put it there.
* Terminate the vector with a null.
*/
blockv = gmem((blockc + 1) * sizeof(blockv[0]));
movmem(lines, blockv, blockc*sizeof(blockv[0]));
blockv[blockc] = NULL;
return blockv;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char **stov(str,maxvect) /* Convert a string of tokens separated
* by white space to an array of pointers
* to the tokens, substituting nulls for
* the white space.
* This routine is used to create the
* depends_on vector in an object node.
*/
char *str; /* String to convert */
int maxvect; /* Maximum size of vector */
{
char **vect, **vp; /* Pointers to the vector */
/* Allocate enough space for a worst-case scenario. */
vp = vect = gmem((maxvect+1) * sizeof(str));
/* Parse the line, storing pointers in vector */
while(*str && --maxvect >= 0) {
skipwhite(str);
*vp++ = str;
skipnonwhite(str);
if (*str)
*str++ = 0; /* replace space with null */
}
*vp = 0; /* null-terminate array */
if (maxvect < 0)
err("Too many dependancies! (%d maximum)",MAXDEP);
return vect;
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void err(msg,param) /* Error message. Prints message with int
* param, then aborts.
*/
char *msg;
int param;
{
printf("FATAL ERROR (%s line %d): ",filename,inputline);
printf(msg,param);
exit();
}
void serr(msg,param) /* As above, except with a string param */
char *msg, *param;
{
printf("FATAL ERROR (%s line %d): ",filename,inputline);
printf(msg,param);
exit();
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void push(elem) /* Push a stack element onto the stack */
char *elem; /* Data to push */
{
STACK *elemptr; /* Pointer to new stack element */
elemptr = gmem(STACKSIZE); /* Allocate space */
elemptr->comline = elem; /* Fill with data */
elemptr->next = stackp; /* Point to previous top */
stackp = elemptr; /* Reset stack pointer */
}
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
char *pop() /* Pop element off stack and return the
* data therein.
*/
{
STACK *elemptr; /* Pointer to top of stack */
if (elemptr = stackp) {
stackp = elemptr->next; /* Set stackp to new top */
return elemptr->comline; /* And return data */
}
else /* If stack is empty, return NULL */
return NULL;
}
/* end */
* * * * * * * * * * * * *